<?php
// +-------------------------------------------------------------------------------
// | DingZone [ A Rapid Development Framework For Dingtalk ]
// +-------------------------------------------------------------------------------
// | DingSyncService.php v1.0
// |
// | Copyright (c) 2014-2018 http://www.heimalanshi.com All rights reserved.
// | Author : Jie
// | Date : 2018-10-11
// +-------------------------------------------------------------------------------


namespace app\core\service;


use app\core\model\EnterpriseBpmsInstance;
use app\core\model\EnterpriseDept;
use app\core\model\EnterpriseUser;
use ding\ApiHelper;
use think\Log;

class DingSyncService {

    /**
     * 同步钉钉部门及人员
     *
     * @param $enterprise
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @throws \think\exception\PDOException
     */
    public static function syncDeptsAndUsers($enterprise) {
        $apiHelper = new ApiHelper($enterprise, null);

        self::_syncDeptUser($enterprise, $apiHelper, EnterpriseDept::ROOT_DEPT_ID);

        $departments = $apiHelper->departmentList();
        foreach ($departments as $department) {
            EnterpriseDept::syncDing($department, $enterprise['id']);

            self::_syncDeptUser($enterprise, $apiHelper, $department['id']);
        }

    }

    /**
     * @param $enterprise
     * @param $apiHelper
     * @param $departmentId
     * @throws \think\exception\DbException
     */
    private static function _syncDeptUser($enterprise, $apiHelper, $departmentId) {
        $offset = 0;
        $size = 1;
        while (true) {
            $userResult = $apiHelper->userList($departmentId, $offset, $size);

            foreach ($userResult['userlist'] as $dingUser) {
                EnterpriseUser::syncDing($dingUser, $enterprise['id']);
                EnterpriseDept::addUserToDept($enterprise['id'], $dingUser['userid'],
                    $departmentId, $dingUser['isLeader'],
                    fetch($dingUser, 'order', null)
                );
                $offset += 1;
            }

            if (!$userResult['hasMore']) {
                break;
            }
        }
    }

    /**
     * 同步审批实例
     *
     * @param $enterprise
     * @param ApiHelper $apiHelper
     * @param $instanceId
     * @param $extData
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public static function syncBpmsInstance($enterprise, ApiHelper $apiHelper, $instanceId, $extData) {
        $dingProcessInstance = $apiHelper->smartworkBpmsProcessinstanceGet($instanceId);
        if (empty($dingProcessInstance)) {
            Log::error("process instance get failed. instance id = " . $instanceId . ". error = " . json_encode($apiHelper->getLastStatus()));
            return;
        }
        $eid = $enterprise['id'];

        $oldInstance = EnterpriseBpmsInstance::get($eid, $instanceId);

        $processCode = self::_fetchExt([$dingProcessInstance, $extData, $oldInstance], 'process_code', '');
        $title = self::_fetchExt([$dingProcessInstance, $extData, $oldInstance], 'title', '');
        $url = self::_fetchExt([$dingProcessInstance, $extData, $oldInstance], 'url', '');
        $createTime = self::_fetchExt([$dingProcessInstance, $extData, $oldInstance], 'create_time', '');
        $finishTime = self::_fetchExt([$dingProcessInstance, $extData, $oldInstance], 'finish_time', '');
        $originatorUserid = self::_fetchExt([$dingProcessInstance, $extData, $oldInstance], 'originator_userid', '');
        $originatorDeptId = self::_fetchExt([$dingProcessInstance, $extData, $oldInstance], 'originator_dept_id', '');
        $originatorDeptName = self::_fetchExt([$dingProcessInstance, $extData, $oldInstance], 'originator_dept_name', '');
        $status = self::_fetchExt([$dingProcessInstance, $extData, $oldInstance], 'status', '');
        $approverUserids = self::_fetchExt([$dingProcessInstance, $extData, $oldInstance], 'approver_userids', '');
        $ccUserids = self::_fetchExt([$dingProcessInstance, $extData, $oldInstance], 'cc_userids', '');
        $formComponentValues = self::_fetchExt([$dingProcessInstance, $extData, $oldInstance], 'form_component_values', '');
        $operationRecords = self::_fetchExt([$dingProcessInstance, $extData, $oldInstance], 'operation_records', '');
        $tasks = self::_fetchExt([$dingProcessInstance, $extData, $oldInstance], 'tasks', '');
        $result = self::_fetchExt([$dingProcessInstance, $extData, $oldInstance], 'result', '');
        $attachedProcessInstanceIds = self::_fetchExt([$dingProcessInstance, $extData, $oldInstance], 'attached_process_instance_ids', '');
        $businessId = self::_fetchExt([$dingProcessInstance, $extData, $oldInstance], 'business_id', '');
        $bizAction = self::_fetchExt([$dingProcessInstance, $extData, $oldInstance], 'biz_action', '');
        $bizCategoryId = self::_fetchExt([$dingProcessInstance, $extData, $oldInstance], 'biz_category_id', '');

        if (is_numeric($createTime)) {
            $createTime = date('Y-m-d H:i:s', $createTime);
        }
        if (is_numeric($finishTime)) {
            $finishTime = date('Y-m-d H:i:s', $finishTime);
        }
        if (!is_string($formComponentValues)) {
            $formComponentValues = json_encode($formComponentValues);
        }
        if (!is_string($operationRecords)) {
            $operationRecords = json_encode($operationRecords);
        }
        if (!is_string($tasks)) {
            $tasks = json_encode($tasks);
        }

        $data = [];
        $data['process_instance_id'] = $instanceId;
        $data['process_code'] = $processCode;
        $data['title'] = $title;
        $data['url'] = $url;
        $data['create_time'] = $createTime;
        $data['finish_time'] = $finishTime;
        $data['originator_userid'] = $originatorUserid;
        $data['originator_dept_id'] = $originatorDeptId;
        $data['originator_dept_name'] = $originatorDeptName;
        $data['status'] = $status;
        $data['approver_userids'] = $approverUserids;
        $data['cc_userids'] = $ccUserids;
        $data['form_component_values'] = $formComponentValues;
        $data['operation_records'] = $operationRecords;
        $data['tasks'] = $tasks;
        $data['result'] = $result;
        $data['attached_process_instance_ids'] = $attachedProcessInstanceIds;
        $data['business_id'] = $businessId;
        $data['biz_action'] = $bizAction;
        $data['biz_category_id'] = $bizCategoryId;
        $data['gmt_created'] = empty($oldInstance) ? time() : $oldInstance['gmt_created'];
        $data['gmt_modified'] = time();

        EnterpriseBpmsInstance::addOrUpdate($eid, $data);
    }

    private static function _fetchExt($items, $field, $defaultVal) {
        foreach ($items as $item) {
            $val = fetch($item, $field);
            if (!empty($val)) {
                return $val;
            }
        }
        return $defaultVal;
    }
}